package utils;

import java.awt.*;
import java.util.Arrays;

/**
 *
 * @author Michał
 */
public class MonoMedianFilter extends FilterBase
{

    protected int maskSize = 3;
    protected int channelShift = 0;

    public void initializeFilter(int maskSize, int channelShift) throws Exception
    {
        if (maskSize % 2 == 0)
        {
            throw new Exception("Rozmiar maski musi być nieparzysty.");
        }
        this.maskSize = maskSize;
        this.channelShift = channelShift;
    }

    public static int monoMedian(int[] values)
    {
        int[] tmp = Arrays.copyOf(values, values.length);
        Arrays.sort(tmp);
        return tmp[tmp.length / 2];
    }

    protected int[] filterPixels(int width, int height, int[] inPixels, Rectangle transformedSpace)
    {
        int index = 0;
        int maskSqr = maskSize * maskSize;
        int maskBounds = maskSize / 2;
        int[] values = new int[maskSqr];
        int[] outPixels = new int[width * height];

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                int k = 0;
                for (int dy = -maskBounds; dy <= maskBounds; dy++)
                {
                    int iy = y + dy;
                    if (0 <= iy && iy < height)
                    {
                        int ioffset = iy * width;
                        for (int dx = -maskBounds; dx <= maskBounds; dx++)
                        {
                            int ix = x + dx;
                            if (0 <= ix && ix < width)
                            {
                                int rgb = inPixels[ioffset + ix];
                                values[k] = (rgb >> channelShift) & 0xff;
                                k++;
                            }
                        }
                    }
                }
                while (k < maskSqr)
                {
                    values[k] = (channelShift == 24) ? 0xff : 0;
                    k++;
                }
                outPixels[index++] = monoMedian(values) << channelShift;
            }
        }
        return outPixels;
    }

    public int[] mergeChannels(int[][] src)
    {
        int noChannels = Math.min(src.length, 4);

        int[] outPixels = new int[src[0].length];
        for (int i = 0; i < noChannels; i++)
        {
            outPixels = addChannels(src[i], outPixels);
        }
        return outPixels;
    }

    protected int[] addChannels(int[] inPixels, int[] outPixels)
    {
        if (inPixels.length != outPixels.length)
        {
            return outPixels;
        }

        for (int i = 0; i < inPixels.length; i++)
        {
            outPixels[i] += inPixels[i];
        }
        return outPixels;
    }
}
